package cqrtplm.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.hustcad.plm.basic.util.TyplmLoggerUtil;
import com.hustcad.plm.pdm.basedrule.service.TyplmBasedRuleService;
import com.hustcad.plm.pdm.basedrule.vo.TyplmBasedLifeStageVO;
import com.hustcad.plm.pdm.ec.module.dto.CreateECADTO;
import com.hustcad.plm.pdm.ec.module.vo.ChgActivityVO;
import com.hustcad.plm.pdm.ec.service.*;
import com.hustcad.plm.pdm.type.model.vo.TypeVueVO;
import com.hustcad.plm.pdm.type.service.TyplmTypeService;
import com.hustcad.plm.pdm.user.service.TyplmUserService;
import com.ty.basic.entity.IdentifierEntity;
import com.ty.basic.entity.change.ChgActRecordLinkDO;
import com.ty.basic.entity.change.ChgActRelDataLinkDO;
import com.ty.basic.entity.change.ChgActivityDO;
import com.ty.basic.entity.change.ChgNoticeDO;
import com.ty.basic.entity.org.UserDO;
import com.ty.basic.entity.type.TypeDO;
import com.ty.basic.session.TyAccountContext;
import cqrtplm.constant.RTPlmConstant;
import cqrtplm.service.RTCreateEcaByEcnService;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Transactional(rollbackFor = {Exception.class})
public class RTCreateEcaByEcnServiceImpl implements RTCreateEcaByEcnService {
    private static final int MAX_RETRY = 150; //设置最大重试次数防止死循环
    private static final Logger log = LoggerFactory.getLogger(RTCreateEcaByEcnServiceImpl.class);
    @Resource
    private TyplmChgActivityService typlmChgActivityService;
    @Resource
    private TyplmChgNoticeService typlmChgNoticeService;
    @Resource
    private TyplmChgNoticeActivityLinkService typlmChgNoticeActivityLinkService;
    @Resource
    private TyplmChgActRelDataLinkService typlmChgActRelDataLinkService;
    @Resource
    private TyplmChgActivityQueryService typlmChgActivityQueryService;
    @Resource
    private TyplmChgActRecordLinkService typlmChgActRecordLinkService;
    @Resource
    private TyplmUserService typlmUserService;
    @Resource
    private TyplmTypeService typlmTypeService;
    @Resource
    private TyplmBasedRuleService typlmBasedRuleService;
    private String strGetEcnByOid = "根据ecnId【{}】获取的变更通告为==>【{}】";
    private String strGetEcaByEcn = "根据ecn查询已存在的eca为==>【{}】";

    @Transactional(rollbackFor = {Exception.class})
    public void createEcaByEcnExt(BigInteger ecnId, String typeName) {
        ChgNoticeDO chgNoticeDO = this.typlmChgNoticeService.selectByPrimaryKey(ecnId);
        TyplmLoggerUtil.debug(log, () -> this.strGetEcnByOid, () -> new Object[]{ecnId, JSON.toJSONString(chgNoticeDO)});
        if (!ObjectUtil.isEmpty(chgNoticeDO)) {
            List<ChgActivityDO> chgActivityDOList = this.typlmChgNoticeActivityLinkService.queryECAByECNId(ecnId);
            if (!CollUtil.isEmpty(chgActivityDOList)) {
                List<ChgActRelDataLinkDO> actRelDataLinkDOList = this.typlmChgActRelDataLinkService.queryChgActRelDataLinkDO(ecnId, (List) null);
                List<ChgActRelDataLinkDO> drawingList = new ArrayList<>();
                for (ChgActRelDataLinkDO relDataLinkDO : actRelDataLinkDOList) {
                    String type = relDataLinkDO.getBotype();
                    if (RTPlmConstant.CADDOC_TYPE.equals(type) || RTPlmConstant.DOC_TYPE.equals(type)) {
                        drawingList.add(relDataLinkDO);
                    }
                }
                actRelDataLinkDOList = drawingList;
                //                TyplmLoggerUtil.debug(log, () -> "获取全部eca关联的变更前对象link为==>【{}】",() -> new Object[]{JSON.toJSONString(actRelDataLinkDOList)});
                if (!CollUtil.isEmpty(actRelDataLinkDOList)) {
                    Map<String, ChgActivityDO> ecaOwnerMap = (Map) chgActivityDOList.stream().collect(Collectors.toMap((item) -> item.getOid() + "_" + item.getOwneroid(), Function.identity(), (a, b) -> a));
                    Map<String, List<ChgActRelDataLinkDO>> linkEcaOwnerMap = (Map) actRelDataLinkDOList.stream().collect(Collectors.groupingBy((item) -> item.getAoid() + "_" + item.getOwneroid()));
                    TypeDO typeDO = this.typlmTypeService.getLastTypeByLogicalidentifier("ty.inteplm.change.CTyChangeActivity");
                    if (!ObjectUtil.isEmpty(typeDO)) {
                        if (StringUtils.isNotEmpty(typeName)) {
                            List<TypeVueVO> typeVueVOS = this.typlmTypeService.queryAccessTypeByNames(Collections.singletonList(typeName));
                            if (CollUtil.isNotEmpty(typeVueVOS) && ((TypeVueVO) typeVueVOS.get(0)).getInthid().startsWith("ty.inteplm.change.CTyChangeActivity")) {
                                typeDO.setName(typeName);
                            }
                        }

                        TyplmBasedLifeStageVO firstStageByCondition = this.typlmBasedRuleService.getFirstStageByCondition(typeDO.getOid(), chgNoticeDO.getContaineroid(), chgNoticeDO.getContainerotype());
                        TyplmLoggerUtil.debug(log, () -> "根据类型的名称、容器的id和容器的类型获取初始化规则", () -> new Object[]{JSON.toJSONString(firstStageByCondition)});
                        Map<String, UserDO> userDOMap = new HashMap();
                        ChgActivityVO tempChgActivity = null;

                        for (Map.Entry<String, List<ChgActRelDataLinkDO>> linkDOEntry : linkEcaOwnerMap.entrySet()) {
                            String key = (String) linkDOEntry.getKey();
                            ChgActivityDO chgActivityDO = (ChgActivityDO) ecaOwnerMap.get(key);
                            if (Objects.nonNull(chgActivityDO)) {
                                ecaOwnerMap.remove(key);
                            } else {
                                String userOid = key.split("_")[1];
                                List<ChgActRelDataLinkDO> value = (List) linkDOEntry.getValue();
                                UserDO userDO = (UserDO) userDOMap.get(userOid);
                                if (Objects.isNull(userDO)) {
                                    userDO = this.typlmUserService.queryUserByKey(new BigInteger(userOid));
                                    userDOMap.put(userOid, userDO);
                                }
                                CreateECADTO eca = this.buildEcaDTO(chgNoticeDO, userDO, firstStageByCondition.getTemplateEntity(), typeDO.getName());
                                ChgActivityVO chgActivityVO = this.typlmChgActivityQueryService.queryECAByNumber(eca.getActivitynumber());
                                for (ChgActRelDataLinkDO linkDO : value) {
                                    if (RTPlmConstant.CADDOC_TYPE.equals(linkDO.getBotype()) || RTPlmConstant.DOC_TYPE.equals(linkDO.getBotype())) {
                                        linkDO.setAoid(chgActivityVO.getOid());
                                        linkDO.setAotype(chgActivityVO.getOtype());
                                        linkDO.setBranchid(chgActivityVO.getBranchid());
                                        this.typlmChgActRelDataLinkService.updateChgActRelDataLinkDO(linkDO);
                                    }
                                }
                                tempChgActivity = chgActivityVO;
                            }
                        }

                        List<ChgActRecordLinkDO> chgActRecordLinkDOList = new ArrayList();
                        for (ChgActivityDO aDo : chgActivityDOList) {
                            if (ecaOwnerMap.containsKey(aDo.getOid() + "_" + aDo.getOwneroid())) {
                                chgActRecordLinkDOList.addAll(this.typlmChgActRecordLinkService.queryObjOidAndOtypeByECAId(aDo.getOid()));
                            }
                        }
                        if (CollUtil.isNotEmpty(chgActRecordLinkDOList)) {
                            if (Objects.isNull(tempChgActivity)) {
                                UserDO creator = (UserDO) userDOMap.get(chgNoticeDO.getCreatoroid());
                                if (Objects.isNull(creator)) {
                                    creator = this.typlmUserService.queryUserByKey(chgNoticeDO.getCreatoroid());
                                }

                                CreateECADTO tempECA = this.buildEcaDTO(chgNoticeDO, creator, firstStageByCondition.getTemplateEntity(), typeDO.getName());
                                tempChgActivity = this.typlmChgActivityQueryService.queryECAByNumber(tempECA.getActivitynumber());
                            }

                            for (ChgActRecordLinkDO recordLinkDO : chgActRecordLinkDOList) {
                                if (RTPlmConstant.CADDOC_TYPE.equals(recordLinkDO.getBotype()) || RTPlmConstant.DOC_TYPE.equals(recordLinkDO.getBotype())) {
                                    recordLinkDO.setAoid(tempChgActivity.getOid());
                                    recordLinkDO.setAotype(tempChgActivity.getOtype());
                                    this.typlmChgActRecordLinkService.updateByPrimaryKey(recordLinkDO);
                                }
                            }
                        }

                        if (CollUtil.isNotEmpty(ecaOwnerMap)) {
                            List<ChgActivityVO> deleteList = Convert.toList(ChgActivityVO.class, ecaOwnerMap.values());
                            this.typlmChgActivityService.batchDeleteEca(deleteList);
                        }
                    }
                }
            }
        }
    }

    @NotNull
    private CreateECADTO buildEcaDTO(ChgNoticeDO chgNoticeDO, UserDO user, IdentifierEntity templateEntity, String typeDefName) {
        CreateECADTO eca = new CreateECADTO();
        TyAccountContext.setUser(user);
        eca.setUserDO(user);
        eca.setOtype("ty.inteplm.change.CTyChangeActivity");
        eca.setCreator(user.getName());
        eca.setOwner(user.getName());
        eca.setActivitynumber("eca" + System.currentTimeMillis());
        eca.setContaineroid(chgNoticeDO.getContaineroid());
        eca.setContainerotype(chgNoticeDO.getContainerotype());
        eca.setEcoId(chgNoticeDO.getOid());
        eca.setLifecycletemplateoid(templateEntity.getOid());
        eca.setTypeDefName(typeDefName);
        TyplmLoggerUtil.debug(log, () -> "待创建的eca对象为==>【{}】", () -> new Object[]{JSON.toJSONString(eca)});
        this.typlmChgActivityService.batchCreateECA(Collections.singletonList(eca));
        return eca;
    }

}
